import re

"""
              +------------------+
              |        0         |
              +-------+----------+
                      |
                      | letter
                      |
              +-------v----------+
              |        1         |
              +-------+----------+
                      |
                      | letter, digit
                      |
              +-------v----------+
              |        0         |
              +-------+----------+
                      |
                      | single delimiter
                      |
              +-------v----------+
              | SINGLE_DELIMITER |
              +-------+----------+
                      |
                      | ':'
                      |
              +-------v----------+
              |        3         |
              +-------+----------+
                      |
                      | '='
                      |
              +-------v----------+
              | DOUBLE_DELIMITER |
              +-------+----------+
                      |
                      | '{'
                      |
              +-------v----------+
              |        4         |
              +-------+----------+
                      |
                      | '}'
                      |
              +-------v----------+
              | COMMENT_END     |
              +-------+----------+
                      |
                      | digit
                      |
              +-------v----------+
              |        2         |
              +-------+----------+
                      |
                      | digit
                      |
              +-------v----------+
              |        2         |
              +-------+----------+
                      |
                      | INTEGER delimiter
                      |
              +-------v----------+
              |        0         |
              +-------+----------+
                      |
                      | '''
                      |
              +-------v----------+
              |        5         |
              +-------+----------+
                      |
                      | character
                      |
              +-------v----------+
              |        5         |
              +-------+----------+
                      |
                      | '''
                      |
              +-------v----------+
              |     CHAR_BOUND   |
              +-------+----------+
                      |
                      | '.'
                      |
              +-------v----------+
              |        6         |
              +-------+----------+
                      |
                      | '.'
                      |
              +-------v----------+
              |     ARRAY_BOUND  |
              +-------+----------+
0: 初始状态
1: 处理标识符
2: 处理整数
3: 处理冒号
4: 处理注释
5: 处理字符
6: 处理数组下标边界符
"""
# Token类别定义
ID = "ID"
RESERVED = "RESERVED"
INTEGER = "INTEGER"  # 无符号整数
CHAR = "CHAR"  # 字符类型

SINGLE_DELIMITER = "SINGLE_DELIMITER"  # 单字符分界符
DOUBLE_DELIMITER = "DOUBLE_DELIMITER"
COMMENT_START = "COMMENT_START"  # 注释头符，即以左花括号 ({) 开始的注释标记
COMMENT_END = "COMMENT_END"
CHAR_BOUND = "CHAR_BOUND"
ARRAY_BOUND = ".."
ERROR = "ERROR"

# 保留字列表
reserved_words = ["if", "repeat", "read", "write", "program", "var", "char", "procedure", "begin", "end", "integer",
                  "while", "type", "else", "then", "fi", "do", "endwh", "array", "return", "record"]

# 输入的SNL源程序
snl_program = '''
program example
var integer x;
begin
    x := 123;
end.
'''


# Token定义
class Token:
    def __init__(self, token_type, value):
        self.token_type = token_type
        self.value = value

    def __repr__(self):
        return f"{self.token_type}: {self.value}"


def lexer(program):
    tokens = []
    state = 0
    buffer = ""

    # 添加一个函数来判断是否为保留字
    def is_reserved(word):
        return word in reserved_words

    for char in program:
        if state == 0:
            # 字母
            if char.isalpha():
                buffer += char
                state = 1
            elif char.isdigit() and char != '0':
                buffer += char
                state = 2
            elif char in "+-*/()[];.<>=,":
                tokens.append(Token(SINGLE_DELIMITER, char))
            elif char == ':':
                buffer += char
                state = 3
            elif char == '{':
                tokens.append(Token(COMMENT_START, char))
                state = 4
            elif char == "'":
                # tokens.append(Token(CHAR_BOUND, char))
                state = 5
            elif char == '.':
                buffer += char
                state = 6
                # 注意空格和缩进的情况也是ok的,所以不用else
            elif char == " " or char == "\n":
                continue
            else:
                tokens.append(Token(ERROR, char))

        elif state == 1:
            # 是字母或者是数字
            if char.isalnum():
                buffer += char
            else:
                # 检查buffer中的内容是否为保留字
                # print(buffer)
                if is_reserved(buffer):
                    tokens.append(Token(RESERVED, buffer))
                else:
                    # print("IDaaaa")
                    # print(buffer)
                    tokens.append(Token(ID, buffer))
                buffer = ""
                state = 0
                # 处理当前字符
                if char in "+-*/()[];.<>=,":
                    tokens.append(Token(SINGLE_DELIMITER, char))
                elif char == ':':
                    buffer += char
                    state = 3
                elif char == " " or char == "\n":
                    continue
                else:
                    tokens.append(Token(ERROR, char))

        elif state == 2:
            if char.isdigit():
                buffer += char
            else:
                tokens.append(Token(INTEGER, int(buffer)))
                buffer = ""
                state = 0
                # 处理当前字符
                if char in "+-*/()[];.<>=,":
                    tokens.append(Token(SINGLE_DELIMITER, char))

        elif state == 3:
            if char == '=':
                buffer += char
                tokens.append(Token(DOUBLE_DELIMITER, buffer))
                buffer = ""
                state = 0
            else:
                tokens.append(Token(ERROR, buffer))
                raise Exception("Invalid character after ':'")

        elif state == 4:
            if char == '}':
                tokens.append(Token(COMMENT_END, char))
                state = 0

        elif state == 5:
            # 需要一个累加的操作
            if char != "'":
                buffer += char
            else:
                tokens.append(Token(CHAR, buffer))
                buffer = ""
                state = 0
                # 处理当前字符
                if char in "+-*/()[];.<>=,":
                    tokens.append(Token(SINGLE_DELIMITER, char))

        elif state == 6:
            if char == '.':
                buffer += char
                tokens.append(Token(ARRAY_BOUND, buffer))
                buffer = ""
                state = 0
            else:
                raise Exception("Invalid character after '.'")

    return tokens


tokens = lexer(snl_program)
